package com.thread;

/**
 * wait的用法：
 * 1.必须配合synchronized使用
 * 2.且使用的必须为同一个对象：synchronized (A)配合A.wait()使用
 * 3.当线程执行到object.wait()时，此线程会同时释放锁synchronized (object)；当它结束了wait后，此线程又会重新去争抢锁synchronized (object)
 *
 * 必须配合synchronized使用；
 * 且在notify后，当前线程不会马上释放锁，要等到当前线程被synchronized修饰的代码执行完，才会释放锁；
 * 使用notify的对象为A，则只能唤醒A.wait()的线程，不能唤醒B.wait()的线程；
 * ****小区别：
 * notify()方法——随机唤醒一个wait的线程
 * notifyAll()方法——唤醒所有wait的线程,让这些被唤醒的线程去争抢，按争抢顺序依次执行
 *
 * @description: 实现线程通信方式一 使用wait/notify
 * 解释：让线程2线进入等待，然后线程1执行完毕之后通知线程2可以运行。前提条件线程2必须先启动
 * 弊端：如果线程1先启动，线程2会进入无线等待状态，永远无法唤醒
 * @create date: 2019/4/20 12:07
 */
public class ThreadNotifyDemo2 {

    public static void main(String[] args) {
        Object obj = new Object();
        Thread thread1 = new Thread(() -> {
            try {
                synchronized (obj) {
                    String threadName = Thread.currentThread().getName();
                    System.out.println("启动线程: " + threadName);
                    for (int i = 0; i < 3; i++) {
                        System.out.println("-->threadName: " + threadName + "i = " + i);
                    }
                    System.out.println("wait threadName: " + threadName);
                    obj.notify();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }, "thread1");
        Thread thread2 = new Thread(() -> {
            try {
                //先sleep,导致线程2没有启动，线程1就已经去唤醒了
//                Thread.sleep(2000);
                synchronized (obj) {
                    obj.wait();
                    String threadName = Thread.currentThread().getName();
                    System.out.println("启动线程: " + threadName);
                    for (int i = 0; i < 3; i++) {
                        System.out.println("-->threadName: " + threadName + "i = " + i);
                    }
                    System.out.println("wait threadName: " + threadName);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }, "thread2");
        thread2.start();
        thread1.start();
    }

}

